package com.lyl.security.module.security.service;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.json.JSONUtil;
import com.lyl.security.common.utils.RedisUtil;
import com.lyl.security.module.security.constant.Constants;
import com.lyl.security.module.security.model.LoginUser;
import com.lyl.security.module.security.properties.SecurityProperties;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * @author Mr.Luo
 * @date 2022-09-13 14:16
 * @desc
 */
@Service
@RequiredArgsConstructor
public class TokenService {
    private final SecurityProperties securityProperties;

    public LoginUser getLoginUser(HttpServletRequest request) {
        //获取token
        String token = getToken(request);
        if (CharSequenceUtil.isNotBlank(token)) {
            try {
                Claims claims = parseToken(token);
                // 解析对应的权限以及用户信息
                String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
                String userKey = Constants.LOGIN_TOKEN_KEY + uuid;
                return JSONUtil.toBean(JSONUtil.toJsonStr(RedisUtil.get(userKey)), LoginUser.class);
            } catch (Exception e) {
            }
        }
        return null;
    }

    private String getToken(HttpServletRequest request) {
        String token = request.getHeader(securityProperties.getToken().getHeader());
        if (CharSequenceUtil.isNotBlank(token) && token.startsWith(Constants.TOKEN_PREFIX)) {
            token = token.replace(Constants.TOKEN_PREFIX, "");
        }
        return token;
    }

    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    private Claims parseToken(String token) {
        return Jwts.parser()
                .setSigningKey(securityProperties.getToken().getSecret())
                .parseClaimsJws(token)
                .getBody();
    }


    public void verifyToken(LoginUser loginUser) {
        long expireTime = loginUser.getExpireTime();
        long currentTime = System.currentTimeMillis();
        if (expireTime - currentTime <= Constants.MILLIS_MINUTE_TEN) {
            refreshToken(loginUser);
        }
    }

    /**
     * 刷新令牌有效期
     *
     * @param loginUser 登录信息
     */
    public void refreshToken(LoginUser loginUser) {
        loginUser.setLoginTime(System.currentTimeMillis());
        loginUser.setExpireTime(loginUser.getLoginTime() + securityProperties.getToken().getExpireTime() * Constants.MILLIS_MINUTE);
        // 根据uuid将loginUser缓存
        String userKey = Constants.LOGIN_TOKEN_KEY + loginUser.getToken();
        RedisUtil.set(userKey, loginUser, securityProperties.getToken().getExpireTime(), TimeUnit.MINUTES);
    }
}
